package com.icedbrew.appfuel;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.Map;

/**
 * Provides base database update implementation through interaction with
 * an {@link EntityManager}. Sub-classes are encouraged to use the associated
 * EntityManager through the {@link #getEntityManager()} method.
 *
 * @author
 */
public abstract class BaseDatabaseUpdate implements IDatabaseUpdate {

	@Autowired
	private EntityManager entityManager;
	private static final Logger LOGGER = LoggerFactory.getLogger("DatabaseUpdate");

	public final void execute() throws AppFuelException {
		try {
			LOGGER.debug("Running Database Update " + toString());
			doDatabaseUpdate();
			LOGGER.debug("Database Update " + toString() + " completed.");
		} catch (Exception ex) {
			throw new AppFuelException("Error encountered running while " +
					"database update " + toString(), ex);
		}
	}

	@Override
	public final String toString() {
		return "[Version: " + getVersion() + ", " +
				"Description: " + getDescription() + "]";
	}

	protected final EntityManager getEntityManager() {
		return entityManager;
	}

	protected final Query createNamedQuery(final String name) {
		return createNamedQuery(name, null);
	}

	protected final Query createNamedQuery(final String name,
	                                       final Map<String, Object> params) {
		final Query query = entityManager.createNamedQuery(name);
		addParametersToQuery(params, query);
		return query;
	}

	protected final Query createNativeQuery(final String sqlString) {
		return createNativeQuery(sqlString, null);
	}

	protected final Query createNativeQuery(final String sqlString,
	                                        final Map<String, Object> params) {
		final Query query = entityManager.createNativeQuery(sqlString);
		addParametersToQuery(params, query);
		return query;
	}


	protected abstract void doDatabaseUpdate() throws Exception;

	private void addParametersToQuery(final Map<String, Object> params,
	                                  final Query query) {
		if (params != null) {
			for (Map.Entry<String, Object> param : params.entrySet()) {
				query.setParameter(param.getKey(), param.getValue());
			}
		}
	}
}
